package Test;

import static org.junit.Assert.*;
import interfaces.ErrorReport;
import interfaces.Pointer;
import interfaces.PointerReader;
import interfaces.PointerWriter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import Pointers.JPointerFactory;
import Pointers.SnesPointer;
import Pointers.JPointerFactory.PointerType;
import Script.JPointerReader;
import Script.JPointerWriter;
import Script.Offset;

/**
 * Tests pointer writing. Uses Snes pointers.
 * 
 * @author Tobias Edin
 */
public class JPointerWriterTest {
	private File testFile;
	private String fileUrl;
	private ArrayList<ErrorReport> err;
	
	@Before
	public void setup() {
		fileUrl = "testFiles/gameTest/tempPrint.smc";
	}
	
	@Test
	public void canPrintSinglePointer() throws IOException {
		HashMap<Integer, Pointer> ps = new HashMap<Integer, Pointer>();
		
		// Create file
		testFile = new File(fileUrl);
		testFile.createNewFile();
		
		// Set up pointer read (for validation)
		ArrayList<Offset> offList = new ArrayList<Offset>();
		offList.add(new Offset(0)); // Read pointer at offset 0.
		PointerReader read = new JPointerReader(testFile, offList, new JPointerFactory(PointerType._2Byte_littleEndian));
		
		// D2EF, converted to EFD2 in the pointer object
		Pointer print = new SnesPointer(0, new Offset(53999), new Offset(0));
		
		// Create pointer set
		HashMap<Integer, Pointer> map = new HashMap<Integer, Pointer>();
		map.put(0, print);
		
		// Write pointers
		JPointerWriter.write(testFile, map);
		
		// Read pointers
		ps = read.getPointers();
		
		assertTrue(ps.size() == 1);
		assertEquals(ps.get(1).getValue(), print.getValue());
	}
	
	@Test
	public void canPrintSinglePointerAtOffsetOtherThanZero() throws IOException {
		HashMap<Integer, Pointer> ps = new HashMap<Integer, Pointer>();
		
		// Create file
		testFile = new File(fileUrl);
		testFile.createNewFile();
		
		// Set up pointer read (for validation)
		ArrayList<Offset> offList = new ArrayList<Offset>();
		offList.add(new Offset(11)); // Read pointer at offset 11.
		PointerReader read = new JPointerReader(testFile, offList, new JPointerFactory(PointerType._2Byte_littleEndian));
		
		// D2EF, converted to EFD2 in the pointer object
		Pointer print = new SnesPointer(0, new Offset(53999), new Offset(11));
		
		// Create pointer set
		HashMap<Integer, Pointer> map = new HashMap<Integer, Pointer>();
		map.put(0, print);
		
		// Write pointers
		JPointerWriter.write(testFile, map);
		
		// Read pointers
		ps = read.getPointers();
		
		assertTrue(ps.size() == 1);
		assertEquals(ps.get(1).getValue(), print.getValue());
	}
	
	@Test
	public void canPrintMultiplePointers() throws IOException {
		HashMap<Integer, Pointer> ps = new HashMap<Integer, Pointer>();
		
		// Create file
		testFile = new File(fileUrl);
		testFile.createNewFile();
		
		// Set up pointer read (for validation)
		ArrayList<Offset> offList = new ArrayList<Offset>();
		offList.add(new Offset(11)); // Read pointer at offset 11.
		offList.add(new Offset(13)); // Read pointer at offset 13.
		PointerReader read = new JPointerReader(testFile, offList, new JPointerFactory(PointerType._2Byte_littleEndian));
		
		// D2EF, converted to EFD2 in the pointer object
		Pointer print = new SnesPointer(0, new Offset(53999), new Offset(11));
		
		// FF22, converted to 22FF in the pointer object
		Pointer print2 = new SnesPointer(1, new Offset(65314), new Offset(13));
		
		// Create pointer set
		HashMap<Integer, Pointer> map = new HashMap<Integer, Pointer>();
		map.put(0, print);
		map.put(1, print2);
		
		// Write pointers
		JPointerWriter.write(testFile, map);
		
		// Read pointers
		ps = read.getPointers();
		
		assertTrue(ps.size() == 2);
		assertEquals(ps.get(1).getValue(), print.getValue());
		assertEquals(ps.get(2).getValue(), print2.getValue());
	}
	
	@After
	public void close() {
		if (!testFile.exists()) {
			System.out.println("Test file not created.");

		} else if (!testFile.delete()) {
			System.out.println("Could not delete test file.");
		}
	}
}
